import { isEmpty } from '@vben/utils';

/**
 * @description 提取菜单树中的每一项uniqueId
 * @param tree 树
 * @returns 每一项uniqueId组成的数组
 */
export const extractPathList = (tree: any[]): any => {
  if (!Array.isArray(tree)) {
    console.warn('tree must be an array');
    return [];
  }
  if (!tree || tree.length === 0) return [];
  const expandedPaths: Array<number | string> = [];
  for (const node of tree) {
    const hasChildren = node.children && node.children.length > 0;
    if (hasChildren) {
      extractPathList(node.children);
    }
    expandedPaths.push(node.id);
  }
  return expandedPaths;
};

/**
 * @description 如果父级下children的length为1，删除children并自动组建唯一uniqueId
 * @param tree 树
 * @param pathList 每一项的id组成的数组
 * @returns 组件唯一uniqueId后的树
 */
export const deleteChildren = (tree: any[], pathList = []): any => {
  if (!Array.isArray(tree)) {
    console.warn('menuTree must be an array');
    return [];
  }
  if (!tree || tree.length === 0) return [];
  for (const [key, node] of tree.entries()) {
    if (node.children && node.children.length === 1) delete node.children;
    node.id = key;
    node.parentId = pathList.length > 0 ? pathList[pathList.length - 1] : null;
    node.pathList = [...pathList, node.id];
    node.uniqueId =
      node.pathList.length > 1 ? node.pathList.join('-') : node.pathList[0];
    const hasChildren = node.children && node.children.length > 0;
    if (hasChildren) {
      deleteChildren(node.children, node.pathList);
    }
  }
  return tree;
};

/**
 * @description 创建层级关系
 * @param tree 树
 * @param pathList 每一项的id组成的数组
 * @returns 创建层级关系后的树
 */
export const buildHierarchyTree = (tree: any[], pathList = []): any => {
  if (!Array.isArray(tree)) {
    console.warn('tree must be an array');
    return [];
  }
  if (!tree || tree.length === 0) return [];
  for (const [key, node] of tree.entries()) {
    node.id = key;
    node.parentId = pathList.length > 0 ? pathList[pathList.length - 1] : null;
    node.pathList = [...pathList, node.id];
    const hasChildren = node.children && node.children.length > 0;
    if (hasChildren) {
      buildHierarchyTree(node.children, node.pathList);
    }
  }
  return tree;
};

/**
 * @description 广度优先遍历，根据唯一uniqueId找当前节点信息
 * @param tree 树
 * @param uniqueId 唯一uniqueId
 * @returns 当前节点信息
 */
export const getNodeByUniqueId = (
  tree: any[],
  uniqueId: number | string,
): any => {
  if (!Array.isArray(tree)) {
    console.warn('menuTree must be an array');
    return [];
  }
  if (!tree || tree.length === 0) return [];
  const item = tree.find((node) => node.uniqueId === uniqueId);
  if (item) return item;
  const childrenList = tree
    .filter((node) => node.children)
    .flatMap((i) => i.children) as unknown;
  return getNodeByUniqueId(childrenList as any[], uniqueId);
};

/**
 * @description 向当前唯一uniqueId节点中追加字段
 * @param tree 树
 * @param uniqueId 唯一uniqueId
 * @param fields 需要追加的字段
 * @returns 追加字段后的树
 */
export const appendFieldByUniqueId = (
  tree: any[],
  uniqueId: number | string,
  fields: object,
): any => {
  if (!Array.isArray(tree)) {
    console.warn('menuTree must be an array');
    return [];
  }
  if (!tree || tree.length === 0) return [];
  for (const node of tree) {
    const hasChildren = node.children && node.children.length > 0;
    if (
      node.uniqueId === uniqueId &&
      Object.prototype.toString.call(fields) === '[object Object]'
    )
      Object.assign(node, fields);
    if (hasChildren) {
      appendFieldByUniqueId(node.children, uniqueId, fields);
    }
  }
  return tree;
};

/**
 * @description 构造树型结构数据
 * @param data 数据源
 * @param id id字段 默认id
 * @param parentId 父节点字段，默认parentId
 * @param children 子节点字段，默认children
 * @returns 追加字段后的树
 */
export const handleTree = (
  data: any[],
  id?: string,
  parentId?: string,
  children?: string,
): any => {
  if (!Array.isArray(data)) {
    console.warn('data must be an array');
    return [];
  }
  const config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children',
  };

  const childrenListMap: any = {};
  const nodeIds: any = {};
  const tree = [];

  for (const d of data) {
    const parentId = d[config.parentId];
    if (isEmpty(childrenListMap[parentId]) || childrenListMap[parentId] === 0) {
      childrenListMap[parentId] = [];
    }
    nodeIds[d[config.id]] = d;
    childrenListMap[parentId]?.push(d);
  }

  for (const d of data) {
    const parentId = d[config.parentId];

    if (nodeIds[parentId] === undefined) {
      tree.push(d);
    }
  }

  for (const t of tree) {
    adaptToChildrenList(t);
  }

  function adaptToChildrenList(o: Record<string, any>) {
    if (childrenListMap[o[config.id]]) {
      o[config.childrenList] = childrenListMap[o[config.id]];
    }
    if (o[config.childrenList]) {
      for (const c of o[config.childrenList]) {
        adaptToChildrenList(c);
      }
    }
  }
  return tree;
};

interface TreeNode<T = any> {
  id: string;
  name: string;
  tag: string;
  checked: number;
  children?: T[];
  parent_id?: string;
}

interface Config {
  id: string;
  group: string;
  childrenList: string;
}

/**
 * @description 构造分组树型结构数据
 * @param data 数据源
 * @param id id字段 默认id
 * @param group 组名，默认tags
 * @param children 子节点字段，默认children
 * @returns 树型结构数据
 */
export const handleGroupToTree = (
  data: Record<string, any>[],
  id = 'id',
  group = 'tags',
  children = 'children',
): TreeNode[] => {
  if (!Array.isArray(data)) {
    console.warn('data must be an array');
    return [];
  }

  const config: Config = { id, group, childrenList: children };
  const groupMap = new Map<string, Record<string, any>[]>();
  const tree: TreeNode[] = [];

  // 构建分组映射
  for (const item of data) {
    const groupName = item[config.group];
    if (!groupMap.has(groupName)) {
      groupMap.set(groupName, []);
    }
    const groupItems = groupMap.get(groupName);
    if (groupItems) {
      groupItems.push(item);
    }
  }

  // 构造树节点
  for (const [groupName, items] of groupMap.entries()) {
    const node: TreeNode = {
      id: `${groupName}-0`,
      name: groupName,
      tag: groupName,
      checked: 0,
      children: items.map((item) => {
        // 为每个 item 添加额外的字段
        const adaptedItem: TreeNode = {
          id: item[config.id],
          name: item.name || item[config.id], // 假设 name 字段可能缺失
          tag: groupName,
          checked: 0,
          ...item, // 保留原始数据的其他字段
        };
        adaptedItem.parent_id = `${groupName}-0`; // 添加父节点 ID
        return adaptedItem;
      }),
    };
    tree.push(node);
  }

  return tree;
};
